package service

import (
	"encoding/json"
	"fmt"
	"sort"

	"lucidity.note/app/common"
	"lucidity.note/app/common/bean"
	"lucidity.note/app/common/db"
	"lucidity.note/app/common/logger"
	"lucidity.note/config"
)

var (
	metaRelationMap map[string]*bean.SuffixItemMetaInfo
	appConfig       *bean.AppConfig
)

func InitConfigService() *bean.AppConfig {
	// App 内部配置文件解析
	appInternalConf := &bean.AppInternalConfig{}
	if err := common.YamlFileParserWithFileData(config.NoteIternalConfig, appInternalConf); nil != err {
		panic(err)
	}

	// CodeMirror 配置
	codemirrorMetaConf := &bean.CodemirrorMetaConfig{}
	if err := common.YamlFileParserWithFileData(config.CodemirrorConfig, codemirrorMetaConf); nil != err {
		panic(err)
	}

	metaRelationMap = make(map[string]*bean.SuffixItemMetaInfo)
	for _, meta := range codemirrorMetaConf.Metas {
		for _, ext := range meta.Exts {
			suffixMeta := &bean.SuffixItemMetaInfo{
				Name:         meta.Name,
				Mime:         meta.Mime,
				Mode:         meta.Mode,
				Ext:          ext,
				Dependencies: meta.Dependencies,
				Addons:       meta.Addons,
			}
			metaRelationMap[ext] = suffixMeta
		}
	}

	dbConn := db.GetDiskInxNustDB()
	appConfig = &bean.AppConfig{
		AppInternalConf: appInternalConf,
		CodemirrorConf:  &bean.CodemirrorConfig{CodemiirrorMata: codemirrorMetaConf},
		AppearanceConf:  initAppearanceConfig(dbConn, appInternalConf),
		GitSyncConf:     initGitSyncConf(dbConn),
		NoteTextConfs:   initNoteTextConf(dbConn, appInternalConf, codemirrorMetaConf),
	}

	return appConfig
}

func GetAppConfig() *bean.AppConfig {
	return appConfig
}

func GetAppInternalConf() *bean.AppInternalConfig {
	return appConfig.AppInternalConf
}

func GetCodeMirrorMetaInfoBySuffix(suffix string) *bean.SuffixItemMetaInfo {
	return metaRelationMap[suffix]
}

func GetAppearanceConfig() *bean.AppearanceConfig {
	return appConfig.AppearanceConf
}

func SetAppearanceConfig(conf *bean.AppearanceConfig) {
	appConfig.AppearanceConf = conf
}

func GetGitSyncConf() *bean.GitSyncConfig {
	return appConfig.GitSyncConf
}

func SetGitSyncConf(conf *bean.GitSyncConfig) {
	appConfig.GitSyncConf = conf
}

func FindNoteTextBySuffix(suffix string) *bean.NoteTextConf {
	var noteTextConf *bean.NoteTextConf
	for _, item := range appConfig.NoteTextConfs {
		if common.Contains(item.Suffixs, suffix) {
			noteTextConf = item
			break
		}
	}
	return noteTextConf
}

func GetNoteTextConf() []*bean.NoteTextConf {
	// 节点排序: 将文件夹和文件分开排序
	sort.Slice(appConfig.NoteTextConfs, func(i, j int) bool {
		return appConfig.NoteTextConfs[i].Enable != appConfig.NoteTextConfs[j].Enable
	})
	return appConfig.NoteTextConfs
}

func SetNoteTextConf(confs []*bean.NoteTextConf) {
	appConfig.NoteTextConfs = confs
}

// 初始化 Git 同步配置
func initGitSyncConf(dbConn *db.DiskIndexConn) *bean.GitSyncConfig {
	// Git 同步设置
	var gitSyncConfig bean.GitSyncConfig
	if value, err := dbConn.Select(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfGitSyncSetting()); nil != err {
		gitSyncConfig = *bean.GetDefaultGitSyncSetting()
		jsonBys, _ := json.Marshal(&gitSyncConfig)
		dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfGitSyncSetting(), string(jsonBys))
	} else {
		if err := json.Unmarshal([]byte(value), &gitSyncConfig); nil != err {
			gitSyncConfig = *bean.GetDefaultGitSyncSetting()
			jsonBys, _ := json.Marshal(&gitSyncConfig)
			dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfGitSyncSetting(), string(jsonBys))
		}
	}
	return &gitSyncConfig
}

// 初始化外观设置
func initAppearanceConfig(dbConn *db.DiskIndexConn, appInternalConf *bean.AppInternalConfig) *bean.AppearanceConfig {
	var editorThemes map[string][]string = make(map[string][]string)
	editorThemes["dark"] = appInternalConf.LucidityNote.EditorSetting.EditorTheme.DarkTheme
	editorThemes["light"] = appInternalConf.LucidityNote.EditorSetting.EditorTheme.LightTheme

	var defaultBks map[string]string = make(map[string]string)
	for index, value := range appInternalConf.LucidityNote.DefaultBkSetting {
		defaultBks[fmt.Sprintf("%d:%s", index, value.Name)] = value.Url
	}

	// 外观设置配置初始化
	var appearanceConf bean.AppearanceConfig
	if value, err := dbConn.Select(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfAppearanceSetting()); nil != err { // 查询失败使用默认的
		appearanceConf = *bean.GetDefaultAppearanceSetting()
		if defaultBks != nil && editorThemes != nil {
			var defaultBkSlice []*bean.DefaultBk = make([]*bean.DefaultBk, 0)

			for k, v := range defaultBks {
				defaultBk := &bean.DefaultBk{
					Name: k,
					Url:  v,
				}
				defaultBkSlice = append(defaultBkSlice, defaultBk)
			}

			appearanceConf.DefaultBkDataSet = defaultBkSlice
			appearanceConf.EditorThemeDataSet = editorThemes
		}
		// 存入数据库中
		jsoBys, _ := json.Marshal(&appearanceConf)
		dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfAppearanceSetting(), string(jsoBys))
	} else {
		if err := json.Unmarshal([]byte(value), &appearanceConf); nil != err {
			logger.FAULT.Println(err.Error())
			appearanceConf = *bean.GetDefaultAppearanceSetting()
			if defaultBks != nil && editorThemes != nil {
				var defaultBkSlice []*bean.DefaultBk = make([]*bean.DefaultBk, 0)

				for k, v := range defaultBks {
					defaultBk := &bean.DefaultBk{
						Name: k,
						Url:  v,
					}
					defaultBkSlice = append(defaultBkSlice, defaultBk)
				}
				appearanceConf.DefaultBkDataSet = defaultBkSlice
				appearanceConf.EditorThemeDataSet = editorThemes
			}
			jsoBys, _ := json.Marshal(&appearanceConf)
			dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfAppearanceSetting(), string(jsoBys))
		}
	}

	return &appearanceConf
}

func initNoteTextConf(dbConn *db.DiskIndexConn, appInternalConf *bean.AppInternalConfig, mate *bean.CodemirrorMetaConfig) []*bean.NoteTextConf {
	var noteTextConfs []*bean.NoteTextConf
	if value, err := dbConn.Select(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfNoteTextConf()); nil != err {
		noteTextConfs = make([]*bean.NoteTextConf, 0)
		for _, item := range mate.Metas {
			isContain := common.Contains(appInternalConf.LucidityNote.DefaultFormats, item.Name)
			noteTextConf := &bean.NoteTextConf{
				Name:     item.Name, // 名称
				Suffixs:  item.Exts, // 后缀
				Enable:   isContain, // 是否启用
				Editable: isContain, // 是否可编辑
			}
			noteTextConfs = append(noteTextConfs, noteTextConf)
		}
		// 存入数据库中
		jsoBys, _ := json.Marshal(&noteTextConfs)
		dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfNoteTextConf(), string(jsoBys))
	} else {
		if err := json.Unmarshal([]byte(value), &noteTextConfs); nil != err {
			logger.FAULT.Println(err.Error())
			noteTextConfs = make([]*bean.NoteTextConf, 0)
			for _, item := range mate.Metas {
				isContain := common.Contains(appInternalConf.LucidityNote.DefaultFormats, item.Name)
				noteTextConf := &bean.NoteTextConf{
					Name:     item.Name, // 名称
					Suffixs:  item.Exts, // 后缀
					Enable:   isContain, // 是否启用
					Editable: isContain, // 是否可编辑
				}
				noteTextConfs = append(noteTextConfs, noteTextConf)
			}
			// 存入数据库中
			jsoBys, _ := json.Marshal(&noteTextConfs)
			dbConn.Insert(bean.GetNustDBBucketOfUserSet(), bean.GetNustDBKeyOfNoteTextConf(), string(jsoBys))
		}
	}
	return noteTextConfs
}
